﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;

using System.Linq;
using System.Xml.Linq;

using ProjectBase.Core;
using ProjectBase.Data;
using ProjectBase.Data.Xml;

using $prjsn$.Common;
using $prjsn$.Common.Data.Services;
using $prjsn$.Entity.Services;

namespace $safeprojectname$.Services.Xml
{
    /// <summary>
    ///     Provides GetAll() which returns all languages in the application
    ///     and extends Find
    /// </summary>
    public class TranslatorDao : BaseXmlDao<Translator, int, TranslatorFilter>, ITranslatorDao
    {
        #region Find
        /// <summary>
        ///     Fills the Criteria list with where statements based on provided filter
        /// </summary>
        /// <param name = "filter"></param>
        /// <returns></returns>
        public override IEnumerable<Translator> Find(TranslatorFilter filter)
        {
            // Equal
            Criteria.Add(entity => entity.ID.IsEqual(filter.IdExact));
            Criteria.Add(entity => entity.Key.IsExact(filter.KeySearch)); // exact match even for the string.Empty
            Criteria.Add(entity => entity.Area.IsExact(filter.AreaSearch));

            // LIKE
            Criteria.Add(entity => entity.Key.IsLike(filter.Key));
            Criteria.Add(entity => entity.Area.IsLike(filter.Area));

            if (filter.SearchedPhrase.IsNotEmpty()) // filter for phrase of selected language
            {
                Criteria.Add(
                    entity =>
                    entity.Phrases.Any(
                        p =>
                        p.Language.Equals(filter.SearchedLanguageName,
                            StringComparison.OrdinalIgnoreCase))
                        ? entity.Phrases.Where(
                            p =>
                            p.Language.Equals(filter.SearchedLanguageName,
                                StringComparison.OrdinalIgnoreCase))
                              .First().Localization.IsLike(filter.SearchedPhrase)
                        : false);
            }

            return GetListByCriteria(filter);
        }
        #endregion Find

        #region GetAll
        public virtual IEnumerable<Translator> GetAll()
        {
            return Find(new TranslatorFilter { TakeRows = int.MaxValue });
        }
        #endregion GetAll

        #region XML - ENTITY mapping
        /// <summary>
        ///     Converts the XElement into the Translator
        /// </summary>
        /// <param name = "element"></param>
        /// <returns></returns>
        protected override Translator CreateEntity(XElement element)
        {
            var entity = FillEntity(new Translator(), element); // base converts ValueTypes and String

            foreach (var phrase in element.Elements("Phrase"))
            {
                entity.Translations[phrase.Attribute("lang").Value] = phrase.Attribute("value").Value;
                entity.Phrases.Add(new Phrase
                {
                    Language = phrase.Attribute("lang").Value,
                    Localization = phrase.Attribute("value").Value,
                    Translator = entity,
                });
            }

            entity.SetId((int)element.Attribute(Str.Common.ID));
            return entity;
        }

        /// <summary>
        ///     Converts the Translator instnace into the XElement
        /// </summary>
        /// <param name = "entity"></param>
        /// <returns></returns>
        protected override XElement CreateElement(Translator entity)
        {
            var element = base.CreateElement(entity); // base converts ValueTypes and String

            foreach (var pair in entity.Translations)
            {
                if (pair.Value.IsNotEmpty())
                {
                    var phrase = new XElement("Phrase");
                    phrase.Add(new XAttribute("lang", pair.Key));
                    phrase.Add(new XAttribute("value", pair.Value));
                    element.Add(phrase);
                }
            }

            return element;
        }
        #endregion XML - ENTITY mapping

        #region Order
        protected override IEnumerable<Translator> AddOrder(IEnumerable<Translator> list, TranslatorFilter filter)
        {
            foreach (var orderBy in filter.OrderBy)
            {
                var pair = orderBy;
                if (typeof(Translator).GetProperties().Any(p => p.Name.Equals(pair.Key, StringComparison.Ordinal)))
                {
                    list = orderBy.Value
                               ? list.OrderBy(entity => entity.GetType().GetProperty(pair.Key).GetValue(entity, null))
                               : list.OrderByDescending(
                                   entity =>
                                   entity.GetType().GetProperty(pair.Key).GetValue(entity, null));
                }
                else if (orderBy.Key.Contains('.')
                         && filter.Is())
                {
                    var language = orderBy.Key.Split('.')[1];
                    if (orderBy.Value)
                    {
                        list = list.OrderBy(entity => entity.Translations.ContainsKey(language)
                                                          ? entity.Translations[language]
                                                          : string.Empty);
                    }
                    else
                    {
                        list = list.OrderByDescending(entity => entity.Translations.ContainsKey(language)
                                                                    ? entity.Translations[language]
                                                                    : string.Empty);
                    }
                }
            }
            return list;
        }
        #endregion

        #region NextId
        /// <summary>
        ///     Incremented 'Next ID' generator. 
        ///     Searches for the max existing used value 
        ///     and returnes that + 1
        /// </summary>
        /// <returns></returns>
        protected override int GetNextId(Translator entity = null)
        {
            var id = 0; // in case there is no element yet
            if (TheList.Any()) // element(s) exist(s) - find the largest ID
            {
                id = TheList.Max<Translator, int>(e => e.ID);
            }
            return ++id;
        }
        #endregion NextId
    }
}